package com.example.runnable;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.bo.MdsBo;
import com.example.bo.SheetBO;
import com.example.config.InitPropertiesConfig;
import com.example.constant.CommonConstant;
import com.example.handler.StatisticHandler;
import com.example.util.CommonUtils;
import com.example.util.ElasticSearchUtils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class EsDemoRunner implements ApplicationRunner {
    @Autowired
    ElasticSearchUtils elasticSearchUtils;

    @Autowired
    StatisticHandler statisticHandler;

    @Autowired
    InitPropertiesConfig initPropertiesConfig;

    private final String index="applog*";
//    private final String index="applog.ceres.bond.ks-2021.08.20";

    @Override
    public void run(ApplicationArguments args) throws Exception {
        testBoolQuery2();
        ExcelWriter excelWriter = null;
        String appParam = initPropertiesConfig.getAppParam();
        List<String[]> params = CommonUtils.getParams(appParam);
        try {
            excelWriter = EasyExcel.write(new FileOutputStream(initPropertiesConfig.getPath())).build();

            for (int i = 0; i < params.size(); i++) {
                String[] param = params.get(i);
                WriteSheet tableNameSheet = EasyExcel.writerSheet(i,"数据"+i).build();
                WriteTable tableNameTable = EasyExcel.writerTable(0).head(SheetBO.class).needHead(true).build();
                List<SheetBO> sheetBOS = statisticHandler.statisticLogMsg(param[0],param[1]);
                excelWriter.write(sheetBOS, tableNameSheet, tableNameTable);
                log.info(JSON.toJSONString(sheetBOS));
            }
//            statisticHandler.statisticAccessLog();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (excelWriter!=null){
                excelWriter.finish();
            }
        }
    }

    public void testAggsTest() throws Exception{
        RestHighLevelClient client = elasticSearchUtils.getRestHighLevelClient();
        // 1.创建SearchRequest对象，并制定索引库名称
        SearchRequest searchRequest = new SearchRequest(index);

        LocalDateTime begin=LocalDateTime.of(2021,8,19,0,0);
        LocalDateTime end=LocalDateTime.of(2021,12,29,0,0);
        //2.创建SearchSourceBuilder对象，设置分组相关参数
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("appname","mds"))
                .must(QueryBuilders.matchQuery("message","Receive Message"))
                .must(QueryBuilders.rangeQuery("@timestamp").gte(begin).lte(end))
        );
//        sourceBuilder.aggregation(
//                AggregationBuilders
//                        .terms("popular_appname")
//                        .field("appname")
//        .subAggregation(
//                AggregationBuilders
//                .dateHistogram("popular_time")
//                .field("@timestamp")
//                .dateHistogramInterval(DateHistogramInterval.HOUR)
//        ));
        sourceBuilder.aggregation(
                AggregationBuilders
                        .dateHistogram("popular_time")
                        .field("@timestamp")
                        .dateHistogramInterval(DateHistogramInterval.HOUR)
        );
        // 分页参数
        sourceBuilder.size(0);
        sourceBuilder.timeout(new TimeValue(90000));

        // 3.添加SearchSourceBuilder对象到SearchRequest对象source中
        searchRequest.source(sourceBuilder);
        // 4.执行查询
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 5.得到查询结果
        SearchHits responseHits = response.getHits();
        long totalHits = responseHits.getTotalHits();
        System.out.println("total："+totalHits);

        // 6.解析分组查询数据
        ParsedDateHistogram aggregation = (ParsedDateHistogram)response.getAggregations().asMap().get("popular_time");
        List<? extends Histogram.Bucket> buckets = aggregation.getBuckets();
        for (Histogram.Bucket bucket : buckets) {
            Object key = bucket.getKey();
            long docCount = bucket.getDocCount();

            System.out.println(bucket.getKey()+" : "+ bucket.getDocCount());
        }

//        Terms terms = (Terms) response.getAggregations().asMap().get("popular_time");
//        List<? extends Terms.Bucket> buckets = terms.getBuckets();
//        for (Terms.Bucket bucket : buckets) {
//            System.out.println(bucket.getKey()+" : "+ bucket.getDocCount());
//        }
    }

    public void testBoolQuery2() throws Exception{
        // 1.构建bool条件对象
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

        // 2.筛选
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("appname", "mds");
        queryBuilder.must(termQueryBuilder);
//        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("message", "Receive Message");
//        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("message", "some instances");
//        queryBuilder.must(fuzzyQueryBuilder);
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("message", "Receive Message");
        queryBuilder.must(matchQueryBuilder);
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("@timestamp")
                .gte(LocalDateTime.of(2021, 8, 19, 0, 0))
                .lte(LocalDateTime.of(2021, 8, 20, 0, 0));
        queryBuilder.must(rangeQueryBuilder);


        printResultByQuery(queryBuilder);
    }

    public void testBoolQuery() throws Exception{
        // 1.构建bool条件对象
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 2.构建matchQuery对象,
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note", "aa");
        queryBuilder.must(matchQueryBuilder);

        // 3.过滤
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "小武");
        queryBuilder.filter(termQueryBuilder);

        // 4.过滤
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(23).lte(27);
        queryBuilder.filter(rangeQueryBuilder);

        printResultByQuery(queryBuilder);
    }

    private void queryAll() throws IOException {
        RestHighLevelClient client = elasticSearchUtils.getRestHighLevelClient();

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                QueryBuilders.matchAllQuery()
        );
        SearchRequest request = new SearchRequest(index);
        request.source(sourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        //  5.1.获取总条数
        long total = searchHits.getTotalHits();
        System.out.println("total = " + total);
        //  5.2.获取SearchHit数组，并遍历
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            //获取分数
            System.out.println("文档得分："+hit.getScore());
            //  - 获取其中的`_source`，是JSON数据
            String json = hit.getSourceAsString();
            //  - 把`_source`反序列化为User对象
            System.out.println("user = " + json);
        }
    }

    public void testTermQuery() throws Exception{
        RestHighLevelClient client = elasticSearchUtils.getRestHighLevelClient();
        //1. 创建SearchSourceBuilder对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //   1. 添加查询条件QueryBuilders.termQuery()
        sourceBuilder.query(QueryBuilders.termQuery("appname", "mds"));
//        sourceBuilder.query(QueryBuilders.termQuery("message", "Receive Message"));
        sourceBuilder.query(QueryBuilders.termQuery("message", "some instances"));
        //2. 创建SearchRequest对象，并制定索引库名称
        SearchRequest request = new SearchRequest(index);
        //3. 添加SearchSourceBuilder对象到SearchRequest对象source中
        request.source(sourceBuilder);
        //4. 发起请求，得到结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //5. 解析结果SearchResponse
        SearchHits searchHits = response.getHits();
        //   1. 获取总条数
        System.out.println("总记录数：" + searchHits.getTotalHits());
        //   2. 获取SearchHits数组，并遍历
        for (SearchHit searchHit : searchHits) {
            //      * 获取其中的`_source`，是JSON数据
            String userJson = searchHit.getSourceAsString();
            //      * 把`_source`反序列化为User对象
            MdsBo mdsBo = JSON.parseObject(userJson, MdsBo.class);
            System.out.println(mdsBo);
        }
    }

    public void printResultByQuery2(QueryBuilder queryBuilder)throws Exception{
        RestHighLevelClient client = elasticSearchUtils.getRestHighLevelClient();
        FieldCapabilitiesRequest request = new FieldCapabilitiesRequest()
                .fields("appname")
                .fields("@timestamp")
                .fields("message")
                .indices(index);
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.query(queryBuilder);
        FieldCapabilitiesResponse response = client.fieldCaps(request, RequestOptions.DEFAULT);
        System.out.println(response);
    }

    public void printResultByQuery(QueryBuilder queryBuilder) throws Exception{
        RestHighLevelClient client = elasticSearchUtils.getRestHighLevelClient();
        //1. 创建SearchSourceBuilder对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //   ************ 构建查询条件************
//        sourceBuilder.fetchSource(false);
//        String[] includeFields = new String[] {"appname", "@timestamp", "message"};
        String[] includeFields = new String[] {"appname", "@timestamp"};
        sourceBuilder.fetchSource(includeFields,null);
//        sourceBuilder.from(0);
        sourceBuilder.size(10);

        //2. 创建SearchRequest对象，并制定索引库名称
        SearchRequest request = new SearchRequest(index);
        //3. 添加SearchSourceBuilder对象到SearchRequest对象source中
        request.source(sourceBuilder);
        //4. 发起请求，得到结果
//        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//        Terms terms = (Terms) response.getAggregations().asMap().get("popular_appname");
//        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        //5. 解析结果SearchResponse
        SearchHits searchHits = response.getHits();
        //   1. 获取总条数
        System.out.println("总记录数：" + searchHits.getTotalHits());
        //   2. 获取SearchHits数组，并遍历
        for (SearchHit searchHit : searchHits) {
            //      * 获取其中的`_source`，是JSON数据
            String userJson = searchHit.getSourceAsString();
            //      * 把`_source`反序列化为User对象
            MdsBo mdsBo = JSON.parseObject(userJson, MdsBo.class);
            System.out.println(mdsBo);
//            JSONObject jsonObject = JSONObject.parseObject(userJson);
//            System.out.println(jsonObject);
            System.out.println(userJson);
        }
    }





//    @Override
//    public void run(ApplicationArguments args) throws Exception {
//        method01();
//    }
//
//    private void method01() throws IOException {
//        String index="applog*";
////        String index="applog.ceres.bond.ks-2021.08.20";
//        boolean indexExist = elasticSearchUtils.isIndexExist(index);
//        SearchSourceBuilder query = new SearchSourceBuilder();
//        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
//        RangeQueryBuilder rangeQueryBuilder = QueryBuilders
//                .rangeQuery("postdate")
//                .from("2021-06-01 00:00:00");
//        boolQueryBuilder.must(rangeQueryBuilder);
//        query.query(boolQueryBuilder);
//        query.from(0);
//        query.size(100);
//        query.timeout(new TimeValue(9000));
//
//
//        List<Map<String, Object>> maps = elasticSearchUtils.searchListData(index, query, "appname");
//        System.out.println(maps);
//    }
}
